package com.haima.sage.bigdata.api.common;

import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class DES3Utils {
    private static final String DESede = "DESede";
    private static final String PKCS5Padding = "DESede/ECB/PKCS5Padding";

    public static String newKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance(DESede);
        keyGenerator.init(168);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] encoded = secretKey.getEncoded();

        //KEY转换
        DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(encoded);
        SecretKeyFactory factory = SecretKeyFactory.getInstance(DESede);
        Key key = factory.generateSecret(deSedeKeySpec);

        return RSAUtils.encryptBASE64(key.getEncoded());
    }

    public static Key getKey(String data) throws Exception {
        byte[] keyBytes = RSAUtils.decryptBASE64(data);
        DESedeKeySpec deSedeKeySpec = new DESedeKeySpec(keyBytes);
        SecretKeyFactory factory = SecretKeyFactory.getInstance(DESede);
        Key key = factory.generateSecret(deSedeKeySpec);
        return key;
    }


    public static String encrypt(String raw, String secret) throws Exception {
        return encrypt(raw.getBytes(), secret);
    }

    public static String encrypt(byte[] raw, String secret) throws Exception {
        Key key = getKey(secret);
        byte[] data =  doFinal(raw, key, Cipher.ENCRYPT_MODE, PKCS5Padding);
        return RSAUtils.encryptBASE64(data);
    }

    public static String decrypt(String raw, String secret) throws Exception {
        byte[] data = RSAUtils.decryptBASE64(raw);
        return decrypt(data, secret);
    }

    public static String decrypt(byte[] raw, String secret) throws Exception {
        Key key = getKey(secret);
        return new String(doFinal(raw, key, Cipher.DECRYPT_MODE, PKCS5Padding));
    }

    public static byte[] doFinal(byte[] raw, Key key, int opmode, String type) throws Exception {
        Cipher cipher = Cipher.getInstance(type);
        cipher.init(opmode, key);
        return cipher.doFinal(raw);
    }
}
